package com.acme.javaschool.intense.bankapp.service;

import java.util.LinkedList;

import com.acme.javaschool.intense.bankapp.exceptions.QueueClosedException;

public class Queue<T> {
	LinkedList<T> data = new LinkedList<>();
	boolean closed = false;
	
	/**
	 * Adds element to queue.
	 * @param element
	 * @throws QueueClosedException 
	 */
	public void add(T element) throws QueueClosedException {
		synchronized (data) {
			if (!closed) {
				data.addFirst(element);
				data.notifyAll();
			} else {
				throw new QueueClosedException();
			}
		}
	}

	/**
	 * Pops element from queue.
	 * @return element or null if queue is empty.
	 */
	public T hardPop() {
		synchronized (data) {
			if (!data.isEmpty()) {
				return data.remove();
			}
			return null;
		}
	}

	/**
	 * Pops element from queue.
	 * @return element.
	 * @throws InterruptedException 
	 * @throws QueueClosedException 
	 */
	public T pop() throws InterruptedException {
		synchronized (data) {
			while (data.isEmpty()) {
				data.wait();
			}
			data.notifyAll();
			return data.remove();
		}
	}

	
	public boolean isClosed() {
		return closed;
	}

	public boolean isEmpty() {
		return data.isEmpty();
	}

	public void close() {
		closed = true;
	}
}
